/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */


#include "stdafx.h"
#include "transfercallback.h"

//#define _TEST


CWiaTransferCallback::CWiaTransferCallback( ImageSite* pImageSite )
	: m_refCount( 1 ),
	m_pImageSite( pImageSite ),
	m_pStream( NULL ),
	m_hGlobal( 0 )
{
}

STDMETHODIMP CWiaTransferCallback::QueryInterface( REFIID iid, LPVOID *ppvObj )
{
	if ( ppvObj == NULL )
	{
		return E_POINTER;
	}

	if ( iid == IID_IUnknown )
	{
		*ppvObj = ( IUnknown* ) this;
	}
	else if ( iid == IID_IWiaTransferCallback )
	{
		*ppvObj = ( IWiaTransferCallback* ) this;
	}
	else if ( iid == IID_IWiaAppErrorHandler )
	{
	//*ppvObj = ( IWiaAppErrorHandler* ) this;
		int i = 0;
	}
	else
	{
		*ppvObj = NULL;
		return E_NOINTERFACE;
	}

	AddRef();

	return S_OK;
}

STDMETHODIMP_(ULONG) CWiaTransferCallback::AddRef()
{
	return InterlockedIncrement( &m_refCount );
}

STDMETHODIMP_(ULONG) CWiaTransferCallback::Release()
{
	LONG refCount = InterlockedDecrement( &m_refCount );

	if ( refCount == 0 )
	{
		delete this;
	}

	return refCount;
}

STDMETHODIMP CWiaTransferCallback::TransferCallback( LONG lFlags, WiaTransferParams *pWiaTransferParams )
{
	HRESULT hr = S_OK;

	static ULONG64 m_size = 0;

	switch ( pWiaTransferParams->lMessage )
	{
	case WIA_TRANSFER_MSG_STATUS:
		{
			int i = 0;
		}
		break;

	case WIA_TRANSFER_MSG_END_OF_STREAM:
		{
#ifdef _TEST
			DWORD ticks = GetTickCount();
#endif
			STATSTG statstg = { 0 };
			hr = m_pStream->Stat( &statstg, STATFLAG_NONAME );

			m_size = pWiaTransferParams->ulTransferredBytes;

			if ( m_size && pWiaTransferParams->hrErrorStatus == S_OK )
			{
				ULONG64 size = m_size;//pWiaTransferParams->ulTransferredBytes;

				HGLOBAL hGlobal;
				hr = GetHGlobalFromStream( m_pStream, &hGlobal );

				void* buffer = GlobalLock( hGlobal );

				void* data = NULL;

				// subtract the file header structure size if it's a bmp file
				//size -= sizeof( BITMAPFILEHEADER );
				//data = new char[ size ];
				//memcpy( data, ( char* ) buffer + sizeof( BITMAPFILEHEADER ), size );

				Pixels image = { 0 };
				bool result = m_pImageSite->createPixels( ( byte_t* ) buffer + sizeof( BITMAPFILEHEADER ), image );

				GlobalUnlock( hGlobal );

				/*IaModelImage image;
				image.dataLength = size;
				image.pImageData = data;*/

				m_pImageSite->imageReady( image );

#ifdef _TEST
			DWORD ticks2 = GetTickCount();
			printf("WIA_TRANSFER_MSG_END_OF_STREAM: in (%i) out(%i) span(%i)\n", ticks, ticks2, ticks2 - ticks);
#endif
			}

			m_pStream->Release();
		}
		break;

	case WIA_TRANSFER_MSG_END_OF_TRANSFER:
		{
			//STATSTG statstg = { 0 };
			//hr = m_pStream->Stat( &statstg, STATFLAG_NONAME );

			//m_pStream->Release();

			/*if ( pWiaTransferParams->hrErrorStatus == S_OK )
			{
				ULONG64 size = m_size;//pWiaTransferParams->ulTransferredBytes;

				HGLOBAL hGlobal;
				hr = GetHGlobalFromStream( m_pStream, &hGlobal );

				void* buffer = GlobalLock( hGlobal );

				void* data = NULL;

				// subtract the file header structure size if it's a bmp file
				size -= sizeof( BITMAPFILEHEADER );

				data = new char[ size ];
				memcpy( data, ( char* ) buffer + sizeof( BITMAPFILEHEADER ), size );

				GlobalUnlock( hGlobal );

				IaModelImage* image = new IaModelImage();
				image->dataLength = size;
				image->pImageData = data;

				m_pImageSite->imageReady( image );
			}*/

			/*if ( m_hGlobal )
			{
				GlobalFree( m_hGlobal );
				m_hGlobal = 0;
			}*/
			/*if ( m_pStream != NULL )
			{
				m_pStream->Release();
				m_pStream = NULL;
			}*/
		}
		break;

	default:
		break;
	}

	return hr;
}

STDMETHODIMP CWiaTransferCallback::GetNextStream( LONG lFlags, BSTR bstrItemName, BSTR bstrFullItemName, IStream **ppDestination )
{
	HRESULT hr = S_OK;

	/*if ( m_pStream != NULL )
	{
		m_pStream->Release();
		m_pStream = NULL;
	}*/

	//if ( !m_hGlobal )
	//{
	//	m_hGlobal = GlobalAlloc( GHND, 8572854 );//4000000 ); //1 << 20 ); //
	//}

	//hr = CreateStreamOnHGlobal( m_hGlobal, FALSE, &m_pStream );
	hr = CreateStreamOnHGlobal( NULL, TRUE, &m_pStream );
	//m_pStream->Seek( 0, STREAM_SEEK_SET, 0 );
	ULONG refs = m_pStream->AddRef();

	//GetHGlobalFromStream( m_pStream, &m_hGlobal );
	//void* buffer = GlobalLock( m_hGlobal );
	//memset( buffer, 10, 8572854 );
	//GlobalUnlock( m_hGlobal );

	if ( hr ) return hr;

	*ppDestination = m_pStream;

	return hr;
}
